<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>使用WebGL绘制一个点</title>
</head>

<body>
  <!--canvas标签创建一个宽高均为500像素，背景为蓝色的矩形画布-->
  <canvas id="webgl" width="500" height="500" style="background-color:#aaaaaa"></canvas>

</body>
<!-- 顶点着色器源码 -->
<script id="vertexShader" type="x-shader/x-vertex">
  attribute vec4 a_Position;//顶点位置坐标
  attribute vec2 a_TexCoord;//纹理坐标
  varying vec2 v_TexCoord;//插值后纹理坐标
  void main() {
    //顶点坐标apos赋值给内置变量gl_Position
    gl_Position = a_Position;
    //纹理坐标插值计算
    v_TexCoord = a_TexCoord;
  }

</script>
<!-- 片元着色器源码 -->
<script id="fragmentShader" type="x-shader/x-fragment">
  //所有float类型数据的精度是highp
  precision highp float;
  // 接收插值后的纹理坐标
  varying vec2 v_TexCoord;
  // 纹理图片像素数据
  uniform sampler2D u_Sampler;
  void main() {
    // 采集纹素，逐片元赋值像素值
    gl_FragColor = texture2D(u_Sampler,v_TexCoord);
  }

</script>

<script>
  //通过getElementById()方法获取canvas画布
  var canvas = document.getElementById('webgl');
  //通过方法getContext()获取WebGL上下文
  var gl = canvas.getContext('webgl');

  //顶点着色器源码
  var vertexShaderSource = document.getElementById('vertexShader').innerText;

  //片元着色器源码
  var fragShaderSource = document.getElementById('fragmentShader').innerText;
  //初始化着色器
  var program = initShader(gl, vertexShaderSource, fragShaderSource);
  /**
   * 从program对象获取相关的变量
   * attribute变量声明的方法使用getAttribLocation()方法
   * uniform变量声明的方法使用getAttribLocation()方法
   **/
  var a_Position = gl.getAttribLocation(program, 'a_Position');
  var a_TexCoord = gl.getAttribLocation(program, 'a_TexCoord');
  var u_Sampler = gl.getUniformLocation(program, 'u_Sampler');
  /**
   * 四个顶点坐标数据data，z轴为零
   * 定义纹理贴图在WebGL坐标系中位置
   **/
  var data = new Float32Array([
    -0.5, 0.5,//左上角——v0
    -0.5, -0.5,//左下角——v1
    0.5, 0.5,//右上角——v2
    0.5, -0.5 //右下角——v3
  ]);
  /**
   * 创建UV纹理坐标数据textureData
   **/
  var textureData = new Float32Array([
    0, 1,//左上角——uv0
    0, 0,//左下角——uv1
    1, 1,//右上角——uv2
    1, 0 //右下角——uv3
  ]);
  /**
   * 加载纹理图像像素数据
   **/
  var image = new Image();
  image.src = 'texture.jpg';//设置图片路径
  image.onload = texture;//图片加载成功后执行texture函数
  /**
   创建缓冲区buffer，向顶点着色器传入顶点位置数据data
   **/
  var buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(a_Position);
  /**
   创建缓冲区textureBuffer，向顶点着色器传入顶点纹理坐标数据textureData
   **/
  var textureBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, textureData, gl.STATIC_DRAW);
  gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(a_TexCoord);
  /**
   创建缓冲区textureBuffer，传入图片纹理数据，然后执行绘制方法drawArrays()
   **/
  function texture() {
    var texture = gl.createTexture();//创建纹理图像缓冲区
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); //纹理图片上下反转
    gl.activeTexture(gl.TEXTURE0);//激活0号纹理单元TEXTURE0
    gl.bindTexture(gl.TEXTURE_2D, texture);//绑定纹理缓冲区
    //设置纹理贴图填充方式(纹理贴图像素尺寸大于顶点绘制区域像素尺寸)
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    //设置纹理贴图填充方式(纹理贴图像素尺寸小于顶点绘制区域像素尺寸)
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    //设置纹素格式，jpg格式对应gl.RGB
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
    gl.uniform1i(u_Sampler, 0);//纹理缓冲区单元TEXTURE0中的颜色数据传入片元着色器
    // 进行绘制
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  }
  /**
   初始化函数initShader()
   **/
  function initShader(gl, vertexShaderSource, fragmentShaderSource) {
    var vertexShader = gl.createShader(gl.VERTEX_SHADER);
    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(vertexShader, vertexShaderSource);
    gl.shaderSource(fragmentShader, fragmentShaderSource);
    gl.compileShader(vertexShader);
    gl.compileShader(fragmentShader);
    var program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    gl.useProgram(program);
    return program;
  }
</script>
</body>

</html>